﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Future.Channel;
using Future.Contract;
using System.Data;
using System.Reflection;

namespace Future.DataAccess
{
    public class DalBase
    {
        private AutoCreateSQLStatement _SQLStatement;
        private BaseEntity _Entity;

        public AutoCreateSQLStatement SQLStatement
        {
            get
            {
                if (_SQLStatement == null)
                {
                    _SQLStatement = new AutoCreateSQLStatement(_Entity);
                }
                return _SQLStatement;
            }
            set { _SQLStatement = value; }
        }

        public BaseEntity Entity
        {
            get { return _Entity; }
            set { _Entity = value; }
        }

        public DalBase(BaseEntity entity)
        {
            Entity = entity;
        }

        public void Exec(ref Task task, ref bool result, ref string errMsg)
        {
            if (task == null)
            {
                result = false;
                errMsg = "Task can't Null";
                return;
            }
            BaseEntity tempEntity;
            SqlDBOperator.shareSQLOperater().BeginTransaction();
            if (task.WcfDataType == WcfDataType.Buffer)
            {
                tempEntity = Common.ZipTools.DecompressionObject<BaseEntity>(task.BufferArgument);
                task.BufferArgument = null;
            }
            else
            {
                tempEntity = LitJson.JsonMapper.ToObject<BaseEntity>(task.JsonArgument);
                task.JsonArgument = null;
            }

            List<BaseEntity> selectEntityList = null;
            switch (task.CommandName)
            {
                case Contract.TaskCommandEnums.Insert:
                    result = Insert(tempEntity, ref errMsg);
                    break;
                case Contract.TaskCommandEnums.Update:
                    result = Update(tempEntity, ref errMsg);
                    break;
                case Contract.TaskCommandEnums.Delete:
                    result = Delete(tempEntity, ref errMsg);
                    break;
                case Contract.TaskCommandEnums.Select:
                    errMsg = "";
                    selectEntityList = Select(tempEntity, ref errMsg);
                    result = errMsg.Length <= 0;
                    if (result)
                    {
                        if (task.WcfDataType == WcfDataType.Buffer)
                        {
                            task.BufferResult = Common.ZipTools.CompressionObject<List<BaseEntity>>(selectEntityList);
                        }
                        else
                        {
                            task.JsonResult = LitJson.JsonMapper.ToJson(selectEntityList);
                        }
                    }
                    break;
            }

            if (result)
            {
                SqlDBOperator.shareSQLOperater().CommitTransaction();
            }
            else
            {
                SqlDBOperator.shareSQLOperater().RollbackTransaction();
            }
            task.CommandName = TaskCommandEnums.None;

            System.Threading.Thread.Sleep(1);
        }

        public virtual bool Insert(BaseEntity entity, ref string errMsg)
        {
            if (entity == null || entity.GetType() != Entity.GetType())
            {
                errMsg = "参数不正确";
                return false;
            }
            try
            {
                object objRet = SqlDBOperator.shareSQLOperater().GetDataSingle(SQLStatement.SimpleInsertStatement, SQLStatement.CreateParameter_Insert(entity));
                int intCount = int.Parse(objRet.ToString());
                if (intCount > 0 && entity.ChildItem != null && entity.ChildItem.Count > 0)
                {
                    BaseEntity tempChildEntity = entity.ChildItem[0];
                    DalBase tempDalBase = Cache.CacheManager.shareCacher().getDALByEntity(tempChildEntity);
                    foreach (BaseEntity itemChild in entity.ChildItem)
                    {
                        System.Reflection.PropertyInfo property = itemChild.GetType().GetProperty(entity.PK);
                        if (property != null)
                        {
                            property.SetValue(itemChild, intCount, null);
                        }

                        if (!tempDalBase.Insert(itemChild, ref errMsg))
                        {
                            intCount = -1;
                            break;
                        }
                    }
                }

                return intCount > 0;
            }
            catch (System.Exception ex)
            {
                errMsg = "Insert Data Has Error." + Environment.NewLine + ex.Message;
                return false;
            }
        }

        public virtual bool Update(BaseEntity entity, ref string errMsg)
        {
            if (entity == null || entity.GetType() != Entity.GetType())
            {
                errMsg = "参数不正确";
                return false;
            }
            try
            {
                int intCount = -1;
                switch (entity.State)
                {
                    case EntityState.Update:
                        intCount = SqlDBOperator.shareSQLOperater().ExecuteSql(SQLStatement.SimpleUpdateStatement, SQLStatement.CreateParameter_Update(entity));
                        break;
                    case EntityState.Insert:
                        intCount = Insert(entity, ref errMsg) ? 1 : -1;
                        break;
                    case EntityState.None:
                    case EntityState.Select:
                        intCount = 1;
                        break;
                }
                if (intCount > 0 && entity.ChildItem != null && entity.ChildItem.Count > 0)
                {
                    BaseEntity tempChildEntity = entity.ChildItem[0];
                    DalBase tempDalBase = Cache.CacheManager.shareCacher().getDALByEntity(tempChildEntity);
                    foreach (BaseEntity itemChild in entity.ChildItem)
                    {
                        if (!tempDalBase.Update(itemChild, ref errMsg))
                        {
                            intCount = -1;
                            break;
                        }
                    }
                }

                return intCount > 0;
            }
            catch (System.Exception ex)
            {
                errMsg = "Update Data Has Error." + Environment.NewLine + ex.Message;
                return false;
            }
        }

        public virtual bool Delete(BaseEntity entity, ref string errMsg)
        {
            if (entity == null || entity.GetType() != Entity.GetType())
            {
                errMsg = "参数不正确";
                return false;
            }
            try
            {
                int intCount = 1;
                if (entity.ChildItem != null && entity.ChildItem.Count > 0)
                {
                    BaseEntity tempChildEntity = entity.ChildItem[0];
                    DalBase tempDalBase = Cache.CacheManager.shareCacher().getDALByEntity(tempChildEntity);
                    foreach (BaseEntity itemChild in entity.ChildItem)
                    {
                        if (!tempDalBase.Delete(itemChild, ref errMsg))
                        {
                            intCount = -1;
                            break;
                        }
                    }
                }
                if (intCount > 0)
                {
                    intCount = SqlDBOperator.shareSQLOperater().ExecuteSql(SQLStatement.SimpleDeleteStatement, SQLStatement.CreateParameter_Delete(entity));
                }
                return intCount > 0;
            }
            catch (System.Exception ex)
            {
                errMsg = "Update Data Has Error." + Environment.NewLine + ex.Message;
                return false;
            }
        }

        public virtual List<BaseEntity> Select(BaseEntity entity, ref string errMsg)
        {
            if (entity == null || entity.GetType() != Entity.GetType())
            {
                errMsg = "参数不正确";
                return null;
            }
            List<BaseEntity> retList = null;
            try
            {
                using (System.Data.IDataReader dataReader = SqlDBOperator.shareSQLOperater().GetReader(SQLStatement.SimpleSelectStatement, SQLStatement.CreateParameter_Select(entity)))
                {
                    retList = SetValueInReaderList(dataReader, entity, ref errMsg);
                }

                if (retList != null && retList.Count > 0 && entity.Child != null)
                {
                    BaseEntity childEntity = entity.Child.GetConstructor(Type.EmptyTypes).Invoke(null) as BaseEntity;
                    DalBase childDAL = Cache.CacheManager.shareCacher().getDALByEntity(childEntity);
                    if (childEntity != null)
                    {
                        foreach (BaseEntity parentEntity in retList)
                        {
                            BaseEntity tempChildEntity = childEntity.Clone() as BaseEntity;
                            PropertyInfo propery = tempChildEntity.GetType().GetProperty(parentEntity.PK);
                            if (propery != null)
                            {
                                //propery.SetValue(tempChildEntity, int.Parse(parentEntity.PK_VALUE.ToString()), null); 
                                propery.SetValue(tempChildEntity, parentEntity.PK_VALUE, null);
                                parentEntity.ChildItem = childDAL.Select(tempChildEntity, ref errMsg);
                                if (errMsg.Length > 0)
                                {
                                    return null;
                                }
                            }
                        }
                    }
                }
            }
            catch (System.Exception ex)
            {
                errMsg = "Select Data Has Error." + Environment.NewLine + ex.Message;
                retList = null;
            }
            return retList;
        }

        private List<BaseEntity> SetValueInReaderList(System.Data.IDataReader dataReader, BaseEntity entityPara, ref string errMsg)
        {
            List<BaseEntity> list = new List<BaseEntity>();
            Type m_Type = entityPara.GetType();
            try
            {
                while (dataReader.Read())
                {
                    BaseEntity entity = entityPara.Clone() as BaseEntity;
                    foreach (System.Reflection.PropertyInfo item in m_Type.GetProperties())
                    {
                        object[] objs = item.GetCustomAttributes(typeof(DBColumnAttribue), true);
                        if (objs.Length == 0) continue;
                        DBColumnAttribue pAttribute = objs[0] as DBColumnAttribue;
                        if (pAttribute.IsDBColumn && pAttribute.IsSelect)
                        {
                            switch (pAttribute.DBType)
                            {
                                case DbType.Int32:
                                    item.SetValue(entity, Int32.Parse(dataReader[item.Name].ToString()), null);
                                    break;
                                case DbType.DateTime:
                                    item.SetValue(entity, DateTime.Parse(dataReader[item.Name].ToString()), null);
                                    break;
                                case DbType.Boolean:
                                    item.SetValue(entity, Boolean.Parse(dataReader[item.Name].ToString()), null);
                                    break;
                                case DbType.Double:
                                    item.SetValue(entity, double.Parse(dataReader[item.Name].ToString()), null);
                                    break;
                                default:
                                    item.SetValue(entity, dataReader[item.Name].ToString(), null);
                                    break;
                            }
                        }
                    }
                    list.Add(entity);
                }
            }
            catch (System.Exception ex)
            {
                errMsg = ex.Message;
                list = null;
            }
            return list;
        }
    }
}
